<?php

/**
 * Created by PhpStorm.
 * User: liuxiu
 * Date: 2022/7/14
 * Time: 18:32
 */

namespace business\elasticsearch\services;


use business\elasticsearch\models\BigDataPurchaseModel;
use common\utils\DomainUtil;

class BigDataPurchaseService
{

    public function getDataList(
        $keyword,
        $province = [],
        $city,
        $publishTime,
        $sourceType,
        $companyType,
        $regStatus,
        $amountLower,
        $amountUpper,
        $phoneType,
        $sortOrder,
        $areaCodes,
        $tags,
        $page,
        $pageSize
    )
    {
        $condition = $this->constructCondition(
            $keyword,
            $province,
            $city,
            $publishTime,
            $sourceType,
            $companyType,
            $regStatus,
            $amountLower,
            $amountUpper,
            $phoneType,
            $areaCodes,
            $tags
        );
        $query = BigDataPurchaseModel::find()
            ->query($condition);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "title" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        if ($sortOrder == 'score') {
            $query->orderBy(['order_score' => SORT_DESC, 'publish_time' => SORT_DESC]);
        } else {
            $query->orderBy(['source_order_score' => SORT_DESC, 'publish_time' => SORT_DESC]);
        }

        $total = $query->count();

        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
        $data = $query->asArray()->all();

        //数据处理
        $result = ['total' => $total, 'list' => []];
        foreach ($data as $dv) {
            $tmp = $dv['_source'];
            $tmp['nameSuggest'] = $tmp['title'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                }
            }

            $tmp = $this->formatPurchase($tmp);//输出字段定义
            $result['list'][] = $tmp;
        }
        return $result;
    }

    public function getDetail($id)
    {
        if (empty($id)) {
            return null;
        }
        $condition['function_score']['query']['term']['_id'] = $id;
        $query = BigDataPurchaseModel::find()
            ->query($condition);
        //分页处理
        $query->offset(0)->limit(1);
        $list = $query->asArray()->all();
        if (!empty($list)) {
            foreach ($list as $dv) {
                $data = $dv['_source'];
                $data['nameSuggest'] = $data['title'];
                if (!empty($dv['highlight'])) {
                    foreach ($dv['highlight'] as $key => $value) {
                        $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                    }
                }
                if (!array_key_exists('end_time', $data)) {
                    $data['end_time'] = '';
                }
                return $data;
            }
        }
        return null;
    }

    public function guessNames($keyword, $pageSize)
    {
        $page = 1;

        $query = [];
        if (!empty($keyword)) {
            $query['function_score']['query']['bool']['must'][] = [
                'match_phrase' => ['title' => $keyword]
            ];
        }

        $query = BigDataPurchaseModel::find()
            ->query($query);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "title" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        $query->orderBy(['_score' => SORT_DESC]);

        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
        $data = $query->asArray()->all();
        //数据处理
        $result = [];
        foreach ($data as $dv) {
            $item = array();
            $tmp = $dv['_source'];
            $tmp['nameSuggest'] = $tmp['title'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                }
            }
            $item['title'] = $tmp['title'];
            $item['titleHL'] = $tmp['titleHL'];
            $result[] = $item;
        }
        return $result;
    }

    private function constructCondition(
        $keyword,
        $province = [],
        $city = [],
        $publishTime = '',
        $sourceType = '',
        $companyType = '',
        $regStatus = 0,
        $amountLower = '',
        $amountUpper = '',
        $phoneType = '',
        $areaCodes = [],
        $tags = []
    )
    {
        $query = [];
        $titleBool = [];
        $companyBool = [];
        $projectBool = [];
        $slop = !empty(\Yii::$app->params['CommonDataDeveloperSlop']) ? \Yii::$app->params['CommonDataDeveloperSlop'] : 2;
        $must = [];
        $query['function_score']['query']['bool']['must'] = &$must;


        if (!empty($keyword)) {
            $should = [];
            $must[] = ['bool' => ['should' => &$should]];
            $titleBool[] = [
                'match_phrase' => ['title' => ["query" => $keyword, 'slop' => $slop]]
            ];
            $should[] = ["bool" => ["must" => $titleBool]];

            $companyBool[] = [
                'match_phrase' => ['developer_name' => ["query" => $keyword, "boost" => 3, 'slop' => $slop]]
            ];
            $should[] = ["bool" => ["must" => $companyBool]];

            $nestedQuery = [];
            $nestedQuery['bool']['should']['match_phrase']['projects.project_name'] = $keyword;
            $projectBool[] = [
                'nested' => [
                    'path' => 'projects',
                    'query' => $nestedQuery
                ]
            ];
            $should[] = ["bool" => ["must" => $projectBool]];
        }

        if (!empty($publishTime)) {
            $dateRange = [];
            if (!empty($publishTime['start_time'])) {
                $dateRange['gte'] = date('Y-m-d', strtotime($publishTime['start_time']));
            }
            if (!empty($publishTime['end_time'])) {
                $dateRange['lt'] = date('Y-m-d', strtotime($publishTime['end_time']));
            }
            if (!empty($dateRange)) {
                $must[] = ['range' => ['publish_time' => $dateRange]];
            }
        }

        if (!empty($amountLower) || !empty($amountUpper)) {
            $amountRange = [];
            if (!empty($amountLower)) {
                $amountRange['gte'] = (float)$amountLower;
            }
            if (!empty($amountUpper)) {
                $amountRange['lte'] = (float)$amountUpper;
            }
            $must[] = ['range' => ['purchase_amount' => $amountRange]];
        }

        if (!empty($phoneType)) {
            $must[] = ['match_phrase' => ['phone_type' => ["query" => $phoneType, 'slop' => $slop]]];
        }

        if ($regStatus == 1) {
            $must[] = ['range' => ['end_time' => ['gte' => date("Y-m-d H:i:s", time())]]];
        } elseif ($regStatus == 2) {
            $must[] = ['range' => ['end_time' => ['lte' => date("Y-m-d H:i:s", time())]]];
        }

        if (!empty($sourceType)) {
            $must[] = ["term" => ['data_source_code' => $sourceType]];
        }

        if (!empty($province) || !empty($city)) {
            $nestedQuery = [];
            if (!empty($province)) {
                $nestedQuery[] = ['terms' => [
                    'projects.province_code.keyword' => $province
                ]];
            }
            if (!empty($city)) {
                $nestedQuery[] = ['terms' => [
                    'projects.city_code.keyword' => $city
                ]];
            }
            $must[] = [
                'nested' => [
                    'path' => 'projects',
                    'query' => [
                        'bool' => [
                            'must' => $nestedQuery
                        ]
                    ]
                ]
            ];
        }

        if (!empty($areaCodes)) {
            $nestedQuery = [];
            $nestedQuery[] = ['terms' => [
                'projects.province_code.keyword' => $areaCodes
            ]];
            $nestedQuery[] = ['terms' => [
                'projects.city_code.keyword' => $areaCodes
            ]];
            $must[] = [
                'nested' => [
                    'path' => 'projects',
                    'query' => [
                        'bool' => [
                            'should' => $nestedQuery
                        ]
                    ]
                ]
            ];
        }


        //企业类型
        if (!empty($companyType)) {
            $must[] = ["term" => ['company_type' => $companyType]];
        }

        //标签
        if (!empty($tags)) {
            $tagShould = [];
            foreach ($tags as $k => $v) {
                if (!empty($v)) {
                    $tagShould[] = ['term' => [$k => $v]];
                }
            }
            $must[] = [
                'bool' => ['should' => $tagShould]
            ];
        }

        return $query;
    }

    public function subscript(
        $keyword,
        $area,
        $source,
        $companyType,
        $purchaseAmountLower,
        $purchaseAmountUpper,
        $contactType,
        $publishTime,
        $createdTime,
        $needOrgCode,
        $page,
        $pageSize
    )
    {
        $condition = $this->subscriptCondition(
            $keyword,
            $area,
            $source,
            $companyType,
            $purchaseAmountLower,
            $purchaseAmountUpper,
            $contactType,
            $publishTime,
            $createdTime,
            $needOrgCode
        );
//        var_dump(json_encode($condition));
        $query = BigDataPurchaseModel::find()
            ->query($condition);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields" => [
                "title" => new \stdClass(),
                "bidding_service_category" => new \stdClass(),
                "developer_name" => new \stdClass(),
                "projects.project_name" => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);
        $query->orderBy(['is_new' => SORT_DESC, 'publish_time' => SORT_DESC, "_score" => SORT_DESC]);

        $total = $query->count();

        //分页处理
        $query->offset(($page - 1) * $pageSize)->limit($pageSize);
        $data = $query->asArray()->all();

        $result = ['total' => $total, 'list' => []];
        foreach ($data as $dv) {
            $tmp = $dv['_source'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                }
            }

            if (isset($tmp['projects.project_nameHL'])) {
                // 如果命中了项目，则只显示命中项目，后续可以优化
                $tmp['combined_projects'] = $tmp['projects.project_nameHL'];
            } else if (!empty($tmp['projects'])) {
                $projectsName = [];
                foreach ($tmp['projects'] as $project) {
                    if ($project['project_name']) $projectsName[] = $project['project_name'];
                }
                $tmp['combined_projects'] = implode(',', $projectsName);
            }
            $result['list'][] = $tmp;
        }

        return $result;
    }

    public function subscriptCondition(
        $keyword,
        $area,
        $source,
        $companyType,
        $purchaseAmountLower,
        $purchaseAmountUpper,
        $contactType,
        $publishTime,
        $createdTime,
        $needOrgCode
    )
    {
        $query = [];
        $slop = !empty(\Yii::$app->params['CommonDataDeveloperSlop']) ? \Yii::$app->params['CommonDataDeveloperSlop'] : 2;
        $must = [];
        $query['function_score']['query']['bool']['must'] = &$must;

        if (!empty($keyword)) {
            $should = [];
            $must[] = ['bool' => ['should' => &$should]];

            foreach ($keyword as $k) {
                $should[] = [
                    'match_phrase' => ['title' => ["query" => $k, 'slop' => $slop]]
                ];
                $should[] = [
                    'match_phrase' => ['bidding_service_category' => ["query" => $k, "boost" => 3, 'slop' => $slop]]
                ];
                $should[] = [
                    'match_phrase' => ['developer_name' => ["query" => $k, "boost" => 3, 'slop' => $slop]]
                ];
                $should[] = [
                    'nested' => [
                        'path' => 'projects',
                        'query' => ['match_phrase' => ['projects.project_name' => $k]]
                    ]
                ];
            }
        }

        if (!empty($needOrgCode)) {
            $must[] = ["term" => ["has_main_data" => ["value" => 1]]];
        }

        if (!empty($area)) {
            $areaShould = [];
            $must[] = [
                'nested' => [
                    'path' => 'projects',
                    'query' => ['bool' => ['should' => &$areaShould]]
                ]
            ];

            $areaShould[] = ["terms" => ['projects.province_code.keyword' => $area]];
            $areaShould[] = ["terms" => ['projects.city_code.keyword' => $area]];
        }

        if (!empty($source)) {
            $must[] = ["terms" => ['data_source_code' => $source]];
        }

        if (!empty($companyType)) {
            $must[] = ["terms" => ['company_type' => $companyType]];
        }

        if (!empty($contactType)) {
            $must[] = ["terms" => ['phone_type' => $contactType]];
        }

        $purchaseAmountRange = [];
        if (!empty($purchaseAmountLower)) {
            $purchaseAmountRange['from'] = $purchaseAmountLower;
        }
        if (!empty($purchaseAmountUpper)) {
            $purchaseAmountRange['to'] = $purchaseAmountUpper;
        }
        if (!empty($purchaseAmountRange)) {
            $must[] = ['range' => ['purchase_amount' => $purchaseAmountRange]];
        }

        if (!empty($publishTime)) {
            $dateRange = [];
            if (!empty($publishTime['start_time'])) {
                $dateRange['gte'] = date('Y-m-d', strtotime($publishTime['start_time']));
            }
            if (!empty($publishTime['end_time'])) {
                $dateRange['lt'] = date('Y-m-d', strtotime($publishTime['end_time']));
            }
            if (!empty($dateRange)) {
                $must[] = ['range' => ['publish_time' => $dateRange]];
            }
        }

        if (!empty($createdTime)) {
            $dateRange = [];
            $dateRange['from'] = $createdTime;
            $dateRange['to'] = date('Y-m-d H:i:s', time());
            $must[] = ['range' => ['created_at' => $dateRange]];
        }

        return $query;
    }

    public function formatPurchase($data)
    {
        //1、显示赋值：因为 es 的值如果为 null 会没有字段
        $return_params = [
            'organizing_code' => 'string',
            'title' => 'string',
            'uid' => 'string',
            'developer_name' => 'string',
            'detail' => 'string',
            'ower' => 'string',
            'ower_mobile' => 'string',
            'agent_organization' => 'string',
            'agent_ower' => 'string',
            'agent_ower_mobile' => 'string',
            'url' => 'string',
            'data_source' => 'string',
            'data_source_code' => 'string',
            'id' => 'string',
            'bidding_service_category' => 'string',
            'company_type' => 'string',
            'end_time' => 'string',
            'publish_time' => 'string',
            'created_at' => 'string',
            'purchase_amount' => 'string',
            'phone_type' => 'string',
            'purchase_demand_cnt_1year' => 'string',
            'cooperation_enterprise_cnt_1year' => 'string',
            'purchase_demand_cnt' => 'string',
            'cooperation_enterprise_cnt' => 'string',
            'developer_id' => 'string',
            'developer_logo' => 'string',
            'order_score' => 'string',
            'corp_province_code' => 'string',
            'source_order_score' => 'string',
            'website_name' => 'string',
            'content_id' => 'string',
            'has_main_data' => 'int',
            'is_new' => 'int',
            'developer_top_100_label' => 'string',
            'new_decorate_expand_label' => 'string',
            'new_land_usage_expand_label' => 'string',
            'new_area_expand_label' => 'string',
            'price_gt_avg_label' => 'string',
        ];

        foreach ($return_params as $rk => $rv) {
            $tmp = isset($data[$rk]) ? $data[$rk] : '';
            $tmp = $tmp === '1990-01-01 00:00:00' ? '' : $tmp;
            if ($rv == 'int') {
                $data[$rk] = (int)$tmp;
            } elseif ($rv == 'array') {
                $data[$rk] = empty($tmp) ? [] : $tmp;
            } else {
                $data[$rk] = $tmp;
            }

        }

        return $data;
    }
}
